import crypto from 'crypto';
import { Logger, AppError, ErrorCode } from '../utils/logger';

// LSPPAY 配置接口
export interface LspPayConfig {
  appId: string;        // 应用ID
  mchNo: string;        // 商户号
  apiKey: string;       // 私钥
  baseUrl: string;      // 网关地址
  notifyIp: string;     // 回调IP
  notifyUrl?: string;   // 回调地址
}

// LSPPAY 创建订单请求参数
export interface CreateLspPayOrderRequest {
  userId: number;
  amount: number;
  paymentMethod: 'BankTransfer' | 'qrPay';
  orderId: string;
  transAccNo: string;      // 银行卡号（必填）
  paymentName: string;     // 付款人真实名称（必填）
  bankCode?: string;       // 银行编码（可选，LSPPAY不需要）
  customerEmail?: string;  // 客户邮箱（可选）
  customerPhone?: string;  // 客户手机号（可选）
  extendParam?: string;    // 透传参数
}

// LSPPAY 创建提现订单请求参数
export interface CreateLspPayPayoutRequest {
  amount: number;
  paymentMethod: 'BankTransfer' | 'qrPay';
  orderId: string;
  receiverName: string;    // 收款人姓名（必填）
  receiverBankCard: string; // 收款银行卡号（必填）
  bankCode?: string;       // 银行编码（可选，LSPPAY不需要）
  customerEmail?: string;  // 客户邮箱（可选）
  customerPhone?: string;  // 客户手机号（可选）
  remark?: string;         // 支付备注（可选）
}

// LSPPAY 统一下单响应
export interface LspPayOrderResponse {
  code: number;
  msg: string;
  data?: {
    payOrderId: string;        // 支付订单号
    mchOrderNo: string;        // 商户订单号
    orderState: number;        // 订单状态
    payDataType: string;       // 支付数据类型
    payData?: string;          // 支付数据
    errCode?: string;          // 渠道错误码
    errMsg?: string;           // 渠道错误描述
  };
  sign?: string;
}

// LSPPAY 代付订单响应
export interface LspPayPayoutResponse {
  code: number;
  msg: string;
  data?: {
    transferId: string;         // 转账订单号
    mchOrderNo: string;         // 商户订单号
    state: number;              // 转账状态：0-订单生成，1-转账中，2-转账成功，3-转账失败，4-转账关闭
    channelOrderNo?: string;    // 渠道转账单号
    confirmWaiting?: boolean;   // 是否等待确认
    errCode?: string;          // 渠道错误码
    errMsg?: string;           // 渠道错误描述
  };
  sign?: string;
}

// LSPPAY 代付查询响应
export interface LspPayPayoutQueryResponse {
  code: number;
  msg: string;
  data?: {
    mchNo: string;              // 商户号
    appId: string;              // 应用ID
    mchOrderNo: string;         // 商户订单号
    transferId: string;         // 转账订单号
    amount: number;             // 转账金额，单位分
    currency: string;           // 货币代码
    ifCode: string;             // 接口代码
    entryType: string;          // 入账方式
    state: number;              // 转账状态
    accountNo: string;          // 收款账号
    accountName?: string;       // 收款人姓名
    bankName?: string;          // 收款人开户行名称
    transferDesc?: string;      // 转账备注信息
    channelOrderNo?: string;    // 渠道转账单号
    confirmWaiting?: boolean;   // 等待确认标志
    errCode?: string;          // 渠道错误码
    errMsg?: string;           // 渠道错误描述
    extParam?: string;         // 扩展参数
    createdAt: number;          // 创建时间，13位时间戳
    successTime?: number;       // 成功时间，13位时间戳
  };
  sign?: string;
}

// LSPPAY 查询订单响应
export interface LspPayQueryResponse {
  code: number;
  msg: string;
  data?: {
    payOrderId: string;        // 支付订单号
    mchNo: string;             // 商户号
    appId: string;             // 应用ID
    mchOrderNo: string;        // 商户订单号
    ifCode: string;            // 支付接口编码
    wayCode: string;           // 支付方式
    amount: number;            // 支付金额
    currency: string;          // 货币代码
    state: number;             // 订单状态
    clientIp?: string;         // 客户端IP
    subject: string;           // 商品标题
    body: string;              // 商品描述
    channelOrderNo?: string;   // 渠道订单号
    errCode?: string;          // 渠道错误码
    errMsg?: string;           // 渠道错误描述
    extParam?: string;         // 扩展参数
    createdAt: number;         // 创建时间
    successTime?: number;      // 成功时间
  };
  sign?: string;
}

export class LspPayService {
  private config: LspPayConfig;

  constructor(config: LspPayConfig) {
    this.config = config;
  }

  /**
   * 生成订单号
   */
  generateOrderId(): string {
    return `LSP${Date.now()}${Math.random().toString(36).substring(2, 6).toUpperCase()}`;
  }

  /**
   * 创建充值订单
   */
  async createRechargeOrder(request: CreateLspPayOrderRequest): Promise<LspPayOrderResponse> {
    Logger.info('LSPPAY创建充值订单', {
      orderId: request.orderId,
      amount: request.amount,
      paymentMethod: request.paymentMethod
    });

    // 根据支付方式确定wayCode
    let wayCode: string;
    switch (request.paymentMethod) {
      case 'qrPay':
        wayCode = 'PROMPTPAY_QR';
        break;
      case 'BankTransfer':
        wayCode = 'MOBILE_BANKING';
        break;
      default:
        wayCode = 'PROMPTPAY_QR';
    }

    // 构建请求参数
    const orderParams = {
      mchNo: this.config.mchNo,
      appId: this.config.appId,
      mchOrderNo: request.orderId,
      wayCode: wayCode,
      amount: Math.round(request.amount * 100), // 转换为分
      currency: 'THB',
      clientIp: '127.0.0.1',
      subject: '泰国充值',
      body: '泰国充值服务',
      notifyUrl: this.config.notifyUrl || `${process.env.APP_BASE_URL || 'https://52.77.253.74:3017'}/api/callback/lsppay`,
      returnUrl: `${process.env.WEB_BASE_URL || 'https://52.77.253.74:5173'}/payment/result`,
      resultPageUrl: `${process.env.WEB_BASE_URL || 'https://52.77.253.74:5173'}/payment/success`,
      cancelUrl: `${process.env.WEB_BASE_URL || 'https://52.77.253.74:5173'}/payment/cancel`,
      expiredTime: 7200, // 2小时过期
      channelExtra: JSON.stringify({
        member_id: request.userId.toString(),
        name: request.paymentName,
        order_attach: `${request.paymentName}@${request.transAccNo}`
      }),
      lang: 'th',
      extParam: request.extendParam || '',
      reqTime: Date.now(),
      version: '1.0',
      signType: 'MD5'
    };

    // 生成签名
    const sign = this.generateSign(orderParams);
    const requestData = { ...orderParams, sign };

    const fullUrl = `${this.config.baseUrl}/api/pay/unifiedOrder`;
    
    Logger.info('LSPPAY发送请求', {
      orderId: request.orderId,
      url: fullUrl,
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Lld': 'th',
        'X-Locale': 'en'
      },
      // 不要记录完整的请求体，因为包含敏感信息
      bodySize: JSON.stringify(requestData).length
    });

    try {
      // 重试逻辑：最多重试2次
      let response: Response | undefined;
      let lastError: Error | null = null;
      
      for (let attempt = 1; attempt <= 3; attempt++) {
        try {
          Logger.info(`LSPPAY请求尝试 ${attempt}/3`, { orderId: request.orderId });
          
          response = await fetch(fullUrl, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              'X-Lld': 'th',
              'X-Locale': 'en'
            },
            body: JSON.stringify(requestData),
            // 添加30秒超时
            signal: AbortSignal.timeout(30000),
          });
          
          // 如果请求成功，跳出重试循环
          break;
          
        } catch (error) {
          lastError = error as Error;
          Logger.warn(`LSPPAY请求失败，尝试 ${attempt}/3`, {
            orderId: request.orderId,
            error: lastError.message,
            willRetry: attempt < 3
          });
          
          // 如果不是最后一次尝试，等待2秒后重试
          if (attempt < 3) {
            await new Promise(resolve => setTimeout(resolve, 2000));
          }
        }
      }
      
      // 如果所有重试都失败了
      if (lastError) {
        throw lastError;
      }

      if (!response) {
        throw new AppError('请求失败：未收到响应', ErrorCode.PAYMENT_API_ERROR, { orderId: request.orderId });
      }

      Logger.info('LSPPAY响应状态', {
        orderId: request.orderId,
        status: response.status,
        statusText: response.statusText,
        headers: Object.fromEntries(response.headers.entries())
      });

      if (!response.ok) {
        // 尝试读取错误响应内容
        let errorText = '';
        try {
          errorText = await response.text();
          Logger.error('LSPPAY API错误响应', {
            orderId: request.orderId,
            status: response.status,
            responseText: errorText
          });
        } catch (e) {
          Logger.error('无法读取LSPPAY错误响应', e);
        }
        
        throw new AppError(`LSPPAY API请求失败: ${response.status} - ${errorText}`, ErrorCode.PAYMENT_API_ERROR);
      }

      const result: LspPayOrderResponse = await response.json();

      Logger.info('LSPPAY充值订单响应', {
        orderId: request.orderId,
        response: result
      });

      return result;
    } catch (error) {
      Logger.error('LSPPAY创建充值订单失败', error, {
        orderId: request.orderId,
        amount: request.amount
      });
      throw new AppError('LSPPAY支付接口调用失败', ErrorCode.PAYMENT_API_ERROR, { orderId: request.orderId });
    }
  }

  /**
   * 创建代付订单
   */
  async createPayoutOrder(request: CreateLspPayPayoutRequest): Promise<LspPayPayoutResponse> {
    Logger.info('LSPPAY创建代付订单', {
      orderId: request.orderId,
      amount: request.amount,
      paymentMethod: request.paymentMethod,
      receiverName: request.receiverName,
      receiverBankCard: request.receiverBankCard
    });

    // 根据支付方式确定入账方式
    let entryType: string;
    switch (request.paymentMethod) {
      case 'BankTransfer':
        entryType = 'CARDS'; // 银行卡
        break;
      case 'qrPay':
        entryType = 'TRUEMONEY'; // TrueMoney QR
        break;
      default:
        entryType = 'CARDS';
    }

    // 构建代付请求参数
    const transferParams = {
      mchNo: this.config.mchNo,
      appId: this.config.appId,
      mchOrderNo: request.orderId,
      entryType: entryType,
      amount: Math.round(request.amount * 100), // 转换为分
      currency: 'THB', // 泰铢
      accountNo: request.receiverBankCard,      // 收款账号
      accountName: request.receiverName,        // 收款人姓名
      bankName: request.bankCode ? this.getBankNameByCode(request.bankCode) : '',  // 收款人开户行名称
      bankCode: request.bankCode || '',         // 收款人开户行代码
      clientIp: '127.0.0.1',                  // 客户端IP
      transferDesc: request.remark || '代付转账', // 转账备注信息
      notifyUrl: this.config.notifyUrl || `${process.env.APP_BASE_URL || 'https://52.77.253.74:3017'}/api/callback/lsppay/payout`,
      channelExtra: '{}',                      // 渠道参数
      extParam: request.orderId,               // 扩展参数，传入订单号方便回调时识别
      reqTime: Date.now(),                     // 请求时间，13位时间戳
      version: '1.0',                          // 接口版本号
      signType: 'MD5'                          // 签名类型
    };

    // 生成签名
    const sign = this.generateSign(transferParams);
    const requestData = { ...transferParams, sign };

    const fullUrl = `${this.config.baseUrl}/api/transferOrder`;
    
    Logger.info('LSPPAY发送代付请求', {
      orderId: request.orderId,
      url: fullUrl,
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Lld': 'th',
        'X-Locale': 'th'
      },
      body: requestData, // 打印完整请求体用于调试
      bodySize: JSON.stringify(requestData).length
    });

    try {
      // 重试逻辑：最多重试2次
      let response: Response | undefined;
      let lastError: Error | null = null;
      
      for (let attempt = 1; attempt <= 3; attempt++) {
        try {
          Logger.info(`LSPPAY代付请求尝试 ${attempt}/3`, { orderId: request.orderId });
          
          response = await fetch(fullUrl, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              'X-Lld': 'th',
              'X-Locale': 'th'
            },
            body: JSON.stringify(requestData),
            // 添加30秒超时
            signal: AbortSignal.timeout(30000),
          });
          
          // 如果请求成功，跳出重试循环
          break;
          
        } catch (error) {
          lastError = error as Error;
          Logger.warn(`LSPPAY代付请求失败，尝试 ${attempt}/3`, {
            orderId: request.orderId,
            error: lastError.message,
            willRetry: attempt < 3
          });
          
          // 如果不是最后一次尝试，等待2秒后重试
          if (attempt < 3) {
            await new Promise(resolve => setTimeout(resolve, 2000));
          }
        }
      }
      
      // 如果所有重试都失败了
      if (lastError) {
        throw lastError;
      }

      if (!response) {
        throw new AppError('请求失败：未收到响应', ErrorCode.PAYMENT_API_ERROR, { orderId: request.orderId });
      }

      Logger.info('LSPPAY代付响应状态', {
        orderId: request.orderId,
        status: response.status,
        statusText: response.statusText,
        headers: Object.fromEntries(response.headers.entries())
      });

      if (!response.ok) {
        // 尝试读取错误响应内容
        let errorText = '';
        try {
          errorText = await response.text();
          Logger.error('LSPPAY代付API错误响应', {
            orderId: request.orderId,
            status: response.status,
            responseText: errorText
          });
        } catch (e) {
          Logger.error('无法读取LSPPAY代付错误响应', e);
        }
        
        throw new AppError(`LSPPAY代付API请求失败: ${response.status} - ${errorText}`, ErrorCode.PAYMENT_API_ERROR);
      }

      const result: LspPayPayoutResponse = await response.json();

      Logger.info('LSPPAY代付订单响应', {
        orderId: request.orderId,
        response: result
      });

      return result;
    } catch (error) {
      Logger.error('LSPPAY创建代付订单失败', error, {
        orderId: request.orderId,
        amount: request.amount
      });
      throw new AppError('LSPPAY代付接口调用失败', ErrorCode.PAYMENT_API_ERROR, { orderId: request.orderId });
    }
  }

  /**
   * 查询代付订单状态
   */
  async queryPayoutOrder(orderId: string): Promise<LspPayPayoutQueryResponse> {
    Logger.info('LSPPAY查询代付订单', { orderId });

    const queryParams = {
      mchNo: this.config.mchNo,
      appId: this.config.appId,
      mchOrderNo: orderId,
      reqTime: Date.now(),
      version: '1.0',
      signType: 'MD5'
    };

    const sign = this.generateSign(queryParams);
    const requestData = { ...queryParams, sign };

    try {
      const response = await fetch(`${this.config.baseUrl}/api/transfer/query`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-Lld': 'th',
          'X-Locale': 'th'
        },
        body: JSON.stringify(requestData),
        // 添加30秒超时
        signal: AbortSignal.timeout(30000),
      });

      if (!response.ok) {
        throw new AppError(`LSPPAY代付查询API请求失败: ${response.status}`, ErrorCode.PAYMENT_API_ERROR);
      }

      const result: LspPayPayoutQueryResponse = await response.json();

      Logger.info('LSPPAY查询代付订单响应', {
        orderId,
        response: result
      });

      return result;
    } catch (error) {
      Logger.error('LSPPAY查询代付订单失败', error, { orderId });
      throw new AppError('LSPPAY代付查询接口调用失败', ErrorCode.PAYMENT_API_ERROR, { orderId });
    }
  }

  /**
   * 查询订单状态
   */
  async queryOrder(orderId: string): Promise<LspPayQueryResponse> {
    Logger.info('LSPPAY查询订单', { orderId });

    const queryParams = {
      mchNo: this.config.mchNo,
      appId: this.config.appId,
      mchOrderNo: orderId,
      reqTime: Date.now(),
      version: '1.0',
      signType: 'MD5'
    };

    const sign = this.generateSign(queryParams);
    const requestData = { ...queryParams, sign };

    try {
      const response = await fetch(`${this.config.baseUrl}/api/pay/query`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-Lld': 'th',
          'X-Locale': 'en'
        },
        body: JSON.stringify(requestData),
        // 添加30秒超时
        signal: AbortSignal.timeout(30000),
      });

      if (!response.ok) {
        throw new AppError(`LSPPAY查询API请求失败: ${response.status}`, ErrorCode.PAYMENT_API_ERROR);
      }

      const result: LspPayQueryResponse = await response.json();

      Logger.info('LSPPAY查询订单响应', {
        orderId,
        response: result
      });

      return result;
    } catch (error) {
      Logger.error('LSPPAY查询订单失败', error, { orderId });
      throw new AppError('LSPPAY查询接口调用失败', ErrorCode.PAYMENT_API_ERROR, { orderId });
    }
  }

  /**
   * 生成MD5签名
   */
  private generateSign(params: Record<string, any>): string {
    // 1. 过滤空值参数
    const filteredParams: Record<string, string> = {};
    for (const [key, value] of Object.entries(params)) {
      if (value !== null && value !== undefined && value !== '') {
        filteredParams[key] = String(value);
      }
    }

    // 2. 按ASCII码排序
    const sortedKeys = Object.keys(filteredParams).sort();

    // 3. 拼接字符串
    const stringA = sortedKeys.map(key => `${key}=${filteredParams[key]}`).join('&');

    // 4. 拼接私钥
    const stringSignTemp = `${stringA}&key=${this.config.apiKey}`;

    // 5. MD5加密并转大写
    const sign = crypto.createHash('md5').update(stringSignTemp, 'utf8').digest('hex').toUpperCase();

    Logger.debug('LSPPAY签名生成', {
      stringA,
      stringSignTemp: stringSignTemp.replace(this.config.apiKey, '***'),
      sign
    });

    return sign;
  }

  /**
   * 验证异步通知签名
   */
  verifyNotification(data: any): boolean {
    if (!data.sign) {
      Logger.warn('LSPPAY异步通知缺少签名');
      return false;
    }

    try {
      const { sign: receivedSign, ...paramsWithoutSign } = data;
      const expectedSign = this.generateSign(paramsWithoutSign);

      const isValid = receivedSign === expectedSign;
      
      if (!isValid) {
        Logger.warn('LSPPAY异步通知签名验证失败', {
          received: receivedSign,
          expected: expectedSign
        });
      }

      return isValid;
    } catch (error) {
      Logger.error('LSPPAY异步通知签名验证出错', error);
      return false;
    }
  }

  /**
   * 根据银行代码获取银行简写名称
   */
  private getBankNameByCode(bankCode: string): string {
    const bankMap: Record<string, string> = {
      '002': 'BBL',
      '004': 'KBANK',
      '006': 'KTB',
      '011': 'TTB',
      '014': 'SCB',
      '017': 'GITI',
      '018': 'SMBC',
      '020': 'SCBT',
      '022': 'CIMBT',
      '024': 'UOBT',
      '025': 'BAY',
      '030': 'GSB',
      '031': 'HSBC',
      '033': 'GHB',
      '034': 'BAAC',
      '039': 'MHCB',
      '066': 'ISBT',
      '067': 'TISCO',
      '069': 'KK',
      '070': 'ICBC Thai',
      '071': 'TCRB',
      '073': 'LH BANK'
    };

    return bankMap[bankCode] || bankCode;
  }

  /**
   * 解析订单状态
   */
  parseOrderState(state: number): string {
    switch (state) {
      case 0:
        return 'INIT_ORDER';      // 订单生成
      case 1:
        return 'NO_PAY';          // 支付中
      case 2:
        return 'SUCCESS';         // 支付成功
      case 3:
        return 'PAY_ERROR';       // 支付失败
      case 4:
        return 'PAY_CANCEL';      // 已撤销
      case 5:
        return 'REFUND';          // 已退款
      case 6:
        return 'CLOSED';          // 订单关闭
      default:
        return 'UNKNOWN';
    }
  }

  /**
   * 解析代付订单状态
   */
  parsePayoutState(state: number): string {
    switch (state) {
      case 0:
        return 'ORDER_CREATED';     // 订单生成
      case 1:
        return 'TRANSFERRING';      // 转账中
      case 2:
        return 'TRANSFER_SUCCESS';  // 转账成功
      case 3:
        return 'TRANSFER_FAILED';   // 转账失败
      case 4:
        return 'TRANSFER_CLOSED';   // 转账关闭
      default:
        return 'UNKNOWN';
    }
  }
}

/**
 * 检查LSPPAY是否已配置
 */
export function isLspPayConfigured(): boolean {
  return !!(
    process.env.LSPPAY_APP_ID &&
    process.env.LSPPAY_MCH_NO &&
    process.env.LSPPAY_API_KEY &&
    process.env.LSPPAY_BASE_URL
  );
}

/**
 * 创建LSPPAY服务实例
 */
export function createLspPayService(): LspPayService {
  if (!isLspPayConfigured()) {
    throw new AppError('LSPPAY配置不完整', ErrorCode.PAYMENT_CONFIG_ERROR);
  }

  const config: LspPayConfig = {
    appId: process.env.LSPPAY_APP_ID!,
    mchNo: process.env.LSPPAY_MCH_NO!,
    apiKey: process.env.LSPPAY_API_KEY!,
    baseUrl: process.env.LSPPAY_BASE_URL!,
    notifyIp: process.env.LSPPAY_NOTIFY_IP || '103.140.154.27',
    notifyUrl: process.env.LSPPAY_NOTIFY_URL || '',
  };

  return new LspPayService(config);
}